package visualizer;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.StringTokenizer;
import javax.swing.JLabel;

class GraphPanel extends Applet implements Runnable {

	Graph graph;
	int nnodes;
	int lghtOrStp;
	Node nodes[] = new Node[100];
	ChangeLight  light[] = new ChangeLight[5];
	CalFlow carpermin[] = new CalFlow[5];
	Thread relaxer, flow;
	int brgflag[] = new int[5];
	double speed=10;
	int carwidth=6, carlength=9;
	int xpos[]= new int[5];
	int ypos=150;
	int brgright[] = new int[5];
	int brgleft[] = new int[5]; 
	int brgtop =ypos+ carlength; 
	int brgbottom=ypos- carlength;
	int rdleft[]=new int[5];
	int rdright[] = new int[5];
	int rdtop= ypos+ carwidth, rdbottom= ypos- carwidth;
	JLabel jLabel1;

	GraphPanel(Graph graph) {


		lghtOrStp=1;                                    //stop :0, light: 1
		this.graph = graph;
		for (int i=0; i<5; i++)
		{
			light[i]= new ChangeLight();
			carpermin[i]= new CalFlow();

			xpos[i]=150*(i+1);
			brgright[i]=xpos[i]- carlength;
			brgleft[i]=xpos[i]+ carlength;
			brgflag[i]=0;
		}
		for(int k=1; k<4; k++){
			rdleft[k]= xpos[k-1]- carwidth;
			rdright[k]= xpos[k-1]+ carwidth; 
		}
		rdleft[0]=0;
		rdright[0]=0;
	}

	int findNode(String lbl,double eventTime,int segmento,double posicion) {
		for (int i = 0 ; i < nnodes ; i++) {
			if (nodes[i].lbl.equals(lbl)) {
				if (segmento == 1 || segmento == 10 || segmento == 2){
					nodes[i].x = posicion;


				}
				else{

					nodes[i].y= posicion;

				}
				System.out.println(lbl+","+eventTime+","+segmento+","+posicion);
				return i;
			}
		}
		System.out.println(lbl+","+eventTime+","+segmento+","+posicion);
		return addNode(lbl,eventTime,segmento,posicion);
	}
	int addNode(String lbl,double eventTime,int segmento, double posicion) {
		int temp;
		Node n = new Node();
		temp = (int)(5*Math.random());
		if (segmento == 1 || segmento == 2 || segmento == 10){
			n.x = posicion;
			n.y= ypos;
			n.carW=carlength;
			n.carL=carwidth;
		}
		else{
			n.x= 132;
			n.y= posicion;
			n.carW=carwidth;
			n.carL=carlength;
		}
//		temp=(int)(3*Math.random());                   // three lanes
//		n.y = 150+50*temp;

		n.road=segmento;
		n.lbl = lbl;
		n.carWaiting=-1;
		nodes[nnodes] = n;
		return nnodes++;
	}

	public void run() {
		int numberOfTokens;
		BufferedReader entrada;
		try {
			entrada = new BufferedReader(new FileReader("c:\\temp\\log.txt"));

			String s = new String();

                        s = entrada.readLine();
			System.out.println(s);
                        while ((s = entrada.readLine())!= null) {
//				lectura de datos
                            String [] result = s.split(",");
                             
                             
                          
			
                                findNode(result[0],Double.valueOf(result[1]).doubleValue(),Integer.valueOf(result[2]).intValue(),Double.valueOf(result[3]).doubleValue());
				relax();
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					break;
				}
			}
			entrada.close();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	synchronized void relax() {


		repaint();
	}

	Node pick;
	double pickoldx, pickoldy;
	Image offscreen;
	Dimension offscreensize;
	Graphics offgraphics;

	final Color selectColor = Color.pink;
	final Color edgeColor = Color.black;
	final Color nodeColor = new Color(200, 220, 100);

	public void paintNode(Graphics g, Node n) {
		int x = (int)n.x;
		int y = (int)n.y;
		g.setColor((n==pick) ? selectColor : nodeColor); 
		int w= n.carW;                             
		int h=n.carL;
		g.fillRect(x - w/2, y - h / 2, w, h);
		g.setColor(Color.black);
		g.drawRect(x - w/2, y - h / 2, w-1, h-1);
		g.drawString(n.lbl, x-w/2+2, y+h/2-2);
	}

	public void paintRoad(Graphics g){
		Dimension d = size();
		g.setColor(Color.gray);
		for(int k=1; k<4; k++){
			g.drawLine(rdleft[k], 0, rdleft[k], rdbottom);
			g.drawLine(rdleft[k], rdtop, rdleft[k], d.height);
			g.drawLine(rdright[k], 0, rdright[k], rdbottom);
			g.drawLine(rdright[k], rdtop, rdright[k], d.height);
			g.drawLine(rdright[k-1], rdtop, rdleft[k], rdtop);
			g.drawLine(rdright[k-1], rdbottom, rdleft[k], rdbottom);
		}
		g.drawLine(rdright[3], rdbottom, d.width, rdbottom);
		g.drawLine(rdright[3], rdtop, d.width, rdtop);   
	}

	public void paintLghtPeriod(Graphics g){
		Font warnFont, dispFont, stopFont;
		warnFont=new Font("Arial", Font.BOLD, 20);
		dispFont=new Font("TimesRoman", 0, 12);
		stopFont=new Font("TimesRoman", Font.BOLD, 14);
		Dimension d = size();

		offgraphics.setColor(Color.black);   
		if(lghtOrStp==1){
			offgraphics.drawString("Traffic Light Period (1: red, 0: green)",  600,50);
			offgraphics.setColor(Color.red);
			offgraphics.drawString("red", 714, 50);
			offgraphics.setColor(Color.green);
			offgraphics.drawString("green", 747, 50);
			offgraphics.setColor(Color.black);
			for(int k=0; k<3; k++){ 
				int tempred= light[k].redpauss/200, tempgreen= light[k].greenpauss/200;
				int temp1=rdright[3]+170;    
				int temp2, temp3, temp4, temp5;
				if (light[k].signal==0){
					temp2=temp1+tempred;
					temp3=30*(k+1)+40;
					temp4= temp2+tempgreen;
					temp5=temp3+12;
				}
				else{
					temp2=temp1+tempgreen;
					temp3=30*(k+1)+40+12;
					temp4= temp2+tempred;
					temp5=temp3-12;
				}
				offgraphics.drawString("Light " +Integer.toString(k+1), temp1-40, (temp5+temp3)/2+5);
				while (temp1<d.width){
					offgraphics.drawLine(temp1, temp3, temp2, temp3);
					offgraphics.drawLine(temp2, temp5, temp4, temp5);
					offgraphics.drawLine(temp1, temp3, temp1, temp5);
					offgraphics.drawLine(temp2, temp3, temp2, temp5);
					temp1=temp4;
					temp2=temp1+tempred;
					temp4=temp2+tempgreen;
				}
			}
			offgraphics.setColor(Color.lightGray);
			offgraphics.fillRect(rdright[3]+328, 30, 15, 130);
			offgraphics.setColor(Color.gray);
			offgraphics.drawRect(rdright[3]+120, 20, 223, 145);
			offgraphics.setColor(Color.black);
		}
		else{
			offgraphics.setFont(warnFont);
			offgraphics.setColor(Color.white);
			offgraphics.fillOval(rdleft[3]+175, rdtop-160, 70, 70);
			offgraphics.setColor(Color.red);
			offgraphics.fillOval(rdleft[3]+180, rdtop-155, 60, 60);
			offgraphics.setColor(Color.white);
			offgraphics.drawString("STOP", rdleft[3]+183, rdtop-116);
			offgraphics.setColor(Color.black);
			offgraphics.setFont(dispFont);
			offgraphics.drawString("(California)", rdleft[3]+185, rdtop-50);
		}
	}

	public void paintLights(Graphics g){
		Font dispFont, stopFont;
		dispFont=new Font("TimesRoman", 0, 12);
		stopFont=new Font("TimesRoman", Font.BOLD, 14);

		g.setFont(dispFont);
		int lightwidth=15;
		for(int k=1; k<4; k++){
			if(lghtOrStp==0){
				g.setColor(Color.red);
				g.fillOval(rdleft[k]-18, rdtop+4, lightwidth, lightwidth); 
				g.setColor(Color.white);
				g.setFont(stopFont);
				g.drawString("S", rdleft[k]-14, rdtop+16);
				g.setFont(dispFont);
			}
			else{ 
				g.setColor(Color.black);
				g.fillRect(rdleft[k]-18, rdtop+4, lightwidth-2, lightwidth-2); 
				g.setColor(light[k-1].signal==1 ? Color.red : Color.green);
				g.fillOval(rdleft[k]-7, rdtop+6, 6, 9); 
				g.setColor(light[k-1].signal==1 ? Color.green : Color.red);
				g.fillOval(rdleft[k]-16, rdtop+2, 9, 6); 
				g.setColor(Color.black);

				g.drawString("Light "+k, rdleft[k]-58, rdtop+17); 
			}
		}    
	}

	public void paintAxies(Graphics g){
		int temp1=610;
		int temp2=350;
		int temp3=temp1+160;
		int temp4= temp2-80;
		offgraphics.setColor(Color.gray);
		offgraphics.drawRect(rdright[3]+120, temp4-35, 220, 130);
		offgraphics.setColor(Color.black);
		offgraphics.drawLine(temp1, temp2, temp3, temp2);
		offgraphics.drawLine(temp3, temp2, temp3-10, temp2-2);
		offgraphics.drawLine(temp3, temp2, temp3-10, temp2+2);
		offgraphics.drawLine(temp1, temp2, temp1, temp4);
		offgraphics.drawLine(temp1, temp4, temp1-2, temp4+10);
		offgraphics.drawLine(temp1, temp4, temp1+2, temp4+10);
		for (int k=1; k<4; k++){
			int grid=20*k;
			offgraphics.drawLine(temp1, temp2- grid, temp1+5, temp2- grid);
			offgraphics.drawString(k+".0", temp1- 20, temp2- grid+5);
		}
		offgraphics.drawString("Time", temp3-10, temp2-10);
		offgraphics.drawString("Traffic Flow ", temp1-20, temp2-95);
		offgraphics.drawString("  (cars/sec.)", temp1-20, temp2-82);

		for (int k=0; k<40; k++){
			if (k>=carpermin[0].count){
				temp3=1;
				offgraphics.setColor(Color.gray);
			}
			else{
				temp3=2;
				offgraphics.setColor(Color.black);
			}
			offgraphics.drawRect(k*3+temp1, temp2 - (int)(carpermin[0].carflow[k]*20+1), temp3, temp3);
		}
	}

	public synchronized void update(Graphics g) {

		Dimension d = size();
		if ((offscreen == null) || (d.width != offscreensize.width) || (d.height != offscreensize.height)) {
			offscreen = createImage(d.width, d.height);
			offscreensize = d;
			offgraphics = offscreen.getGraphics();
		}

		offgraphics.setColor(getBackground());
		offgraphics.fillRect(0, 0, d.width, d.height);
		paintRoad(offgraphics);
//		draw lights
	//	paintLights(offgraphics);
//		draw light period
	//	paintLghtPeriod(offgraphics);
//		draw axies for the flow chart
	//	paintAxies(offgraphics);
//		draw cars             
		for (int i = 0 ; i < nnodes ; i++) {
			paintNode(offgraphics, nodes[i]);
		}               
		g.drawImage(offscreen, 0, 0, null);
	}

	public synchronized boolean mouseDown(Event evt, int x, int y) {
		double bestdist = Double.MAX_VALUE;
		for (int i = 0 ; i < nnodes ; i++) {
			Node n = nodes[i];
			double dist = (n.x - x) * (n.x - x) + (n.y - y) * (n.y - y);
			if (dist < bestdist) {
				pick = n;
				pickoldx=n.x;
				pickoldy=n.y;
				bestdist = dist;
			}
		}
		pick.x = x;
		pick.y = y;
		repaint();
		return true;
	}

	public synchronized boolean mouseDrag(Event evt, int x, int y) {
		pick.x = x;
		pick.y = y;
		repaint();
		return true;
	}

	public synchronized boolean mouseUp(Event evt, int x, int y) {
		boolean insidelane;
		pick.x = x;
		pick.y = y;
		insidelane=false;
		for (int k=1; k<4; k++)
			if (x>rdleft[k]&&x<rdright[k])
			{
				pick.road=k;
				pick.x=xpos[k-1];
				pick.carW= carwidth;
				pick.carL= carlength;
				insidelane=true;
			}
		if (!insidelane&&(y<rdtop&&y>rdbottom))
		{
			pick.road=0;
			pick.y=ypos;
			pick.carW= carlength;
			pick.carL= carwidth;

		}
		else if(!insidelane)
		{
			pick.x=pickoldx;
			pick.y=pickoldy;
		}
		pick = null;

		repaint();
		return true;
	}

	public void start() {
		relaxer = new Thread(this);
		relaxer.start();
	}
	public void stop() {
		relaxer.stop();
	}
}